home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.0-b / stk-3 / blt-for-STk-3.0 / blt-1.9 / src / bltGrBar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-19  |  32.7 KB  |  1,134 lines

  1. /*
  2.  * bltGrBar.c --
  3.  *
  4.  *    This module implements a elements in the graph widget
  5.  *    for the Tk toolkit.
  6.  *
  7.  * Copyright 1991-1994 by AT&T Bell Laboratories.
  8.  * Permission to use, copy, modify, and distribute this software
  9.  * and its documentation for any purpose and without fee is hereby
  10.  * granted, provided that the above copyright notice appear in all
  11.  * copies and that both that the copyright notice and warranty
  12.  * disclaimer appear in supporting documentation, and that the
  13.  * names of AT&T Bell Laboratories any of their entities not be used
  14.  * in advertising or publicity pertaining to distribution of the
  15.  * software without specific, written prior permission.
  16.  *
  17.  * AT&T disclaims all warranties with regard to this software, including
  18.  * all implied warranties of merchantability and fitness.  In no event
  19.  * shall AT&T be liable for any special, indirect or consequential
  20.  * damages or any damages whatsoever resulting from loss of use, data
  21.  * or profits, whether in an action of contract, negligence or other
  22.  * tortuous action, arising out of or in connection with the use or
  23.  * performance of this software.
  24.  *
  25.  */
  26.  
  27. #include "blt.h"
  28. #include "bltGraph.h"
  29. #include <ctype.h>
  30. #include <X11/Xutil.h>
  31. #include <X11/Xatom.h>
  32.  
  33.  
  34. /*
  35.  * Sun's bundled and unbundled C compilers can't grok static function
  36.  * typedefs (it can handle extern) like
  37.  *
  38.  *     static Tk_OptionParseProc parseProc;
  39.  *      static Tk_OptionPrintProc printProc;
  40.  *
  41.  * Provide forward declarations here:
  42. */
  43.  
  44. static int ParseColorList _ANSI_ARGS_((ClientData clientData,
  45.     Tcl_Interp *interp, Tk_Window tkwin, char *value, char *widgRec,
  46.     int offset));
  47. static char *PrintColorList _ANSI_ARGS_((ClientData clientData,
  48.     Tk_Window tkwin, char *widgRec, int offset,
  49.     Tcl_FreeProc **freeProcPtr));
  50. static int ParseBitmapList _ANSI_ARGS_((ClientData clientData,
  51.     Tcl_Interp *interp, Tk_Window tkwin, char *value, char *widgRec,
  52.     int offset));
  53. static char *PrintBitmapList _ANSI_ARGS_((ClientData clientData,
  54.     Tk_Window tkwin, char *widgRec, int offset,
  55.     Tcl_FreeProc **freeProcPtr));
  56.  
  57. #include "bltGrElem.h"
  58.  
  59. extern Tk_CustomOption bltXVectorOption;
  60. extern Tk_CustomOption bltYVectorOption;
  61. extern Tk_CustomOption bltTwinOption;
  62. extern Tk_CustomOption bltXAxisFlagsOption;
  63. extern Tk_CustomOption bltYAxisFlagsOption;
  64.  
  65. static Tk_CustomOption ColorListOption =
  66. {
  67.     ParseColorList, PrintColorList, (ClientData)0
  68. };
  69. static Tk_CustomOption BitmapListOption =
  70. {
  71.     ParseBitmapList, PrintBitmapList, (ClientData)0
  72. };
  73.  
  74. #define DEF_SEG_SIZE    8    /* Default size of the static array.
  75.                  * Each element represents a segment of
  76.                  * the bar. */
  77.  
  78. typedef struct {
  79.     Tcl_Interp *interp;        /* Interpreter of the graph widget */
  80.     ElementClassType type;    /* Type of element is BAR_ELEMENT */
  81.     unsigned int flags;
  82.     Tk_Uid id;            /* Identifier to refer the element.
  83.                  * Used in the "insert", "delete", or
  84.                  * "show", commands. */
  85.     int mapped;            /* If non-zero, element is currently
  86.                  * visible.*/
  87.     Tk_ConfigSpec *configSpecs;    /* Configuration specifications */
  88.     char *label;        /* Label displayed in legend */
  89.     SymbolType symbol;        /* Element symbol type */
  90.     double symbolScale;        /* Size of symbol as a percentage of
  91.                  * the drawing area. */
  92.     unsigned int symbolSize;    /* Computed size of symbol in pixels. */
  93.     Vector x, y;        /* Contains array of numeric values */
  94.     unsigned int axisFlags;    /* Indicates which axes to map element's
  95.                  * coordinates onto */
  96.     int *activeArr;        /* Array of indices of active data
  97.                  * points (malloc-ed). Initially points
  98.                  * to static storage "staticArr". */
  99.     int staticArr[DEF_ACTIVE_SIZE];
  100.     int numActivePoints;    /* Number of active data points. If
  101.                  * zero and active bit is set in
  102.                  * "flags", then all data points are
  103.                  * active. */
  104.  
  105.     ElemConfigProc *configProc;
  106.     ElemDestroyProc *destroyProc;
  107.     ElemDisplayProc *displayProc;
  108.     ElemLimitsProc *limitsProc;
  109.     ElemDistanceProc *closestProc;
  110.     ElemLayoutProc *layoutProc;
  111.     ElemPrintProc *printProc;
  112.     ElemDrawSymbolsProc *drawSymbolsProc;
  113.     ElemPrintSymbolsProc *printSymbolsProc;
  114.  
  115.     /*
  116.      * Bar specific attributes
  117.      */
  118.     Tk_3DBorder border;        /* 3D border and background color */
  119.     int borderWidth;        /* 3D border width of bar */
  120.     int relief;            /* Relief of bar */
  121.  
  122.     Tk_3DBorder activeBorder;
  123.     XColor *activeFg;
  124.     GC activeGC;
  125.  
  126.     Pixmap *bitmapArr;        /* Array of bitmaps for each segment of
  127.                  * the bar (malloc-ed). */
  128.     int numBitmaps;        /* # of bitmaps in the array */
  129.     XColor **colorArr;        /* Array of normal foreground colors
  130.                  * for each segment of the bar
  131.                  * (malloc-ed). */
  132.     int numColors;        /* # of normal foreground colors in
  133.                  * the array */
  134.     GC *gcArr;            /* Array of GC pointers for each
  135.                  * segment of the bar (malloc-ed). */
  136.     int stacked;        /* If non-zero, the bar y-values
  137.                  * represent a set of stacked bar
  138.                  * segments */
  139.     int padX;            /* Spacing on either side of bar */
  140.     XRectangle *segments;    /* Array of rectangle coordinates
  141.                  * composing the dimension of each
  142.                  * segments of the bar. By default, is
  143.                  * set to "segArr". */
  144.     XRectangle segArr[DEF_SEG_SIZE];
  145.     int numSegments;        /* Number of segments in the bar */
  146.  
  147. } Bar;
  148.  
  149. #define DEF_BAR_ACTIVE_BG_COLOR "red"
  150. #define DEF_BAR_ACTIVE_BG_MONO    WHITE
  151. #define DEF_BAR_ACTIVE_FG_COLOR "pink"
  152. #define DEF_BAR_ACTIVE_FG_MONO     BLACK
  153. #define DEF_BAR_BG_COLOR    "navyblue"
  154. #define DEF_BAR_BG_MONO        BLACK
  155. #define DEF_BAR_BORDERWIDTH    "2"
  156. #define DEF_BAR_DATA        (char *)NULL
  157. #define DEF_BAR_FG_COLOR         "blue"
  158. #define DEF_BAR_FG_MONO        WHITE
  159. #define DEF_BAR_LABEL        (char *)NULL
  160. #define DEF_BAR_RELIEF        "raised"
  161. #define DEF_BAR_STACKED        "0"
  162. #define DEF_BAR_STIPPLE        ""
  163. #define DEF_BAR_X_AXIS        "x"
  164. #define DEF_BAR_X_DATA        (char *)NULL
  165. #define DEF_BAR_Y_AXIS        "y"
  166. #define DEF_BAR_Y_DATA        (char *)NULL
  167.  
  168. static Tk_ConfigSpec configSpecs[] =
  169. {
  170.     {TK_CONFIG_BORDER, "-activebackground",
  171.     "elemActiveBackground", "Background",
  172.     DEF_BAR_ACTIVE_BG_COLOR, Tk_Offset(Bar, activeBorder),
  173.     TK_CONFIG_COLOR_ONLY},
  174.     {TK_CONFIG_BORDER, "-activebackground",
  175.     "elemActiveBackground", "Background",
  176.     DEF_BAR_ACTIVE_BG_MONO, Tk_Offset(Bar, activeBorder),
  177.     TK_CONFIG_MONO_ONLY},
  178.     {TK_CONFIG_COLOR, "-activeforeground",
  179.     "elemActiveForeground", "Foreground",
  180.     DEF_BAR_ACTIVE_FG_COLOR, Tk_Offset(Bar, activeFg),
  181.     TK_CONFIG_COLOR_ONLY},
  182.     {TK_CONFIG_COLOR, "-activeforeground",
  183.     "elemActiveForeground", "Foreground",
  184.     DEF_BAR_ACTIVE_FG_MONO, Tk_Offset(Bar, activeFg),
  185.     TK_CONFIG_MONO_ONLY},
  186.     {TK_CONFIG_BORDER, "-background", "elemBackground", "Background",
  187.     DEF_BAR_BG_COLOR, Tk_Offset(Bar, border),
  188.     TK_CONFIG_COLOR_ONLY},
  189.     {TK_CONFIG_BORDER, "-background", "elemBackground", "Background",
  190.     DEF_BAR_BG_COLOR, Tk_Offset(Bar, border),
  191.     TK_CONFIG_MONO_ONLY},
  192.     {TK_CONFIG_SYNONYM, "-bd", "elemBorderwidth", (char *)NULL,
  193.     (char *)NULL, 0, 0},
  194.     {TK_CONFIG_SYNONYM, "-bg", "elemBackground", (char *)NULL,
  195.     (char *)NULL, 0, 0},
  196.     {TK_CONFIG_PIXELS, "-borderwidth", "elemBorderwidth", "Borderwidth",
  197.     DEF_BAR_BORDERWIDTH, Tk_Offset(Bar, borderWidth), 0},
  198.     {TK_CONFIG_SYNONYM, "-fg", "elemForeground", (char *)NULL,
  199.     (char *)NULL, 0, 0},
  200.     {TK_CONFIG_CUSTOM, "-data", "elemData", "Data",
  201.     (char *)NULL, 0, 0, &bltTwinOption},
  202.     {TK_CONFIG_CUSTOM, "-foreground", "elemForeground", "Foreground",
  203.     DEF_BAR_FG_COLOR, Tk_Offset(Bar, colorArr),
  204.     TK_CONFIG_COLOR_ONLY, &ColorListOption},
  205.     {TK_CONFIG_CUSTOM, "-foreground", "elemForeground", "Foreground",
  206.     DEF_BAR_FG_COLOR, Tk_Offset(Bar, colorArr),
  207.     TK_CONFIG_MONO_ONLY, &ColorListOption},
  208.     {TK_CONFIG_STRING, "-label", "elemLabel", "Label",
  209.     DEF_BAR_LABEL, Tk_Offset(Bar, label), TK_CONFIG_NULL_OK},
  210.     {TK_CONFIG_CUSTOM, "-mapx", "elemMapX", "MapX",
  211.     DEF_BAR_X_AXIS, Tk_Offset(Bar, axisFlags),
  212.     TK_CONFIG_DONT_SET_DEFAULT, &bltXAxisFlagsOption},
  213.     {TK_CONFIG_CUSTOM, "-mapy", "elemMapY", "MapY",
  214.     DEF_BAR_Y_AXIS, Tk_Offset(Bar, axisFlags),
  215.     TK_CONFIG_DONT_SET_DEFAULT, &bltYAxisFlagsOption},
  216.     {TK_CONFIG_RELIEF, "-relief", "elemRelief", "Relief",
  217.     DEF_BAR_RELIEF, Tk_Offset(Bar, relief), 0},
  218.     {TK_CONFIG_BOOLEAN, "-stacked", "elemStacked", "Stacked",
  219.     DEF_BAR_STACKED, Tk_Offset(Bar, stacked), 0},
  220.     {TK_CONFIG_CUSTOM, "-stipple", "elemStipple", "Stipple",
  221.     DEF_BAR_STIPPLE, Tk_Offset(Bar, bitmapArr), 0, &BitmapListOption},
  222.     {TK_CONFIG_CUSTOM, "-xdata", "elemXdata", "Xdata",
  223.     DEF_BAR_X_DATA, 0, 0, &bltXVectorOption},
  224.     {TK_CONFIG_CUSTOM, "-ydata", "elemYdata", "Ydata",
  225.     DEF_BAR_Y_DATA, 0, 0, &bltYVectorOption},
  226.     {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
  227. };
  228.  
  229.  
  230. /* ----------------------------------------------------------------------
  231.  * Custom option parse and print procedures
  232.  * ----------------------------------------------------------------------
  233.  */
  234.  
  235. /*
  236.  *----------------------------------------------------------------------
  237.  *
  238.  * ParseColorList --
  239.  *
  240.  *    Convert a list of color names in to an array of XColor pointers.
  241.  *
  242.  * Results:
  243.  *    The return value is a standard Tcl result.
  244.  *
  245.  * Side Effects:
  246.  *    An array of color pointers in allocated and filled.
  247.  *
  248.  *----------------------------------------------------------------------
  249.  */
  250. /*ARGSUSED*/
  251. static int
  252. ParseColorList(clientData, interp, tkwin, value, widgRec, offset)
  253.     ClientData clientData;    /* unused */
  254.     Tcl_Interp *interp;        /* Interpreter to send results back to */
  255.     Tk_Window tkwin;        /*  */
  256.     char *value;        /* List of foreground color names */
  257.     char *widgRec;        /* Bar element record */
  258.     int offset;            /* unused */
  259. {
  260.     Bar *barPtr = (Bar *)widgRec;
  261.     register int i;
  262.     int numColors;
  263.     XColor **colorArr = NULL, **colorPtrPtr;
  264.     char **colorNames;
  265.  
  266.     colorNames = NULL;
  267.     if (Tcl_SplitList(interp, value, &numColors, &colorNames) != TCL_OK) {
  268.     return TCL_ERROR;
  269.     }
  270.     if (numColors < 1) {
  271.     interp->result = "no colors specified";
  272.     goto error;
  273.     }
  274.     colorArr = (XColor **)malloc(sizeof(XColor *) * (numColors + 1));
  275.     if (colorArr == NULL) {
  276.     goto error;
  277.     }
  278.     for (i = 0; i < numColors; i++) {
  279.     colorArr[i] = Tk_GetColor(interp, tkwin,
  280.         Tk_GetUid(colorNames[i]));
  281.     if (colorArr[i] == NULL) {
  282.         goto error;
  283.     }
  284.     }
  285.     colorArr[i] = NULL;
  286.     free((char *)colorNames);
  287.     if (barPtr->colorArr != NULL) {
  288.     for (colorPtrPtr = barPtr->colorArr; *colorPtrPtr != NULL;
  289.         colorPtrPtr++) {
  290.         Tk_FreeColor(*colorPtrPtr);
  291.     }
  292.     free((char *)barPtr->colorArr);
  293.     }
  294.     barPtr->colorArr = colorArr;
  295.     barPtr->numColors = numColors;
  296.     return TCL_OK;
  297.  
  298.   error:
  299.     if (colorArr != NULL) {
  300.     for (colorPtrPtr = colorArr; *colorPtrPtr != NULL; colorPtrPtr++) {
  301.         Tk_FreeColor(*colorPtrPtr);
  302.     }
  303.     free((char *)colorArr);
  304.     }
  305.     if (colorNames != NULL) {
  306.     free((char *)colorNames);
  307.     }
  308.     return TCL_ERROR;
  309. }
  310.  
  311. /*
  312.  *----------------------------------------------------------------------
  313.  *
  314.  * PrintColorList --
  315.  *
  316.  *    Convert the array of color pointers into a list of color names.
  317.  *
  318.  * Results:
  319.  *    The string representing the list of color names is returned.
  320.  *
  321.  *----------------------------------------------------------------------
  322.  */
  323. /*ARGSUSED*/
  324. static char *
  325. PrintColorList(clientData, tkwin, widgRec, offset, freeProcPtr)
  326.     ClientData clientData;    /* Type of axis vector to print */
  327.     Tk_Window tkwin;        /* not used */
  328.     char *widgRec;        /* Bar element record */
  329.     int offset;            /* not used */
  330.     Tcl_FreeProc **freeProcPtr;    /* Memory deallocation scheme to use */
  331. {
  332.     Bar *barPtr = (Bar *)(widgRec);
  333.     Tcl_DString buffer;
  334.     char *result;
  335.     register XColor **colorPtrPtr;
  336.  
  337.     Tcl_DStringInit(&buffer);
  338.     for (colorPtrPtr = barPtr->colorArr; *colorPtrPtr != NULL; colorPtrPtr++) {
  339.     Tcl_DStringAppendElement(&buffer, Tk_NameOfColor(*colorPtrPtr));
  340.     }
  341.     result = Tcl_DStringValue(&buffer);
  342.     result = strdup(result);
  343.     *freeProcPtr = (Tcl_FreeProc *)free;
  344.     Tcl_DStringFree(&buffer);
  345.     return (result);
  346. }
  347.  
  348. /*
  349.  *----------------------------------------------------------------------
  350.  *
  351.  * ParseBitmapList --
  352.  *
  353.  *    Convert a list of bitmap names in to an array of XBitmap pointers.
  354.  *
  355.  * Results:
  356.  *    The return value is a standard Tcl result.
  357.  *
  358.  * Side Effects:
  359.  *    An array of bitmap pointers in allocated and filled.
  360.  *
  361.  *----------------------------------------------------------------------
  362.  */
  363. /*ARGSUSED*/
  364. static int
  365. ParseBitmapList(clientData, interp, tkwin, value, widgRec, offset)
  366.     ClientData clientData;    /* unused */
  367.     Tcl_Interp *interp;        /* Interpreter to send results back to */
  368.     Tk_Window tkwin;        /*  */
  369.     char *value;        /* List of bitmap names */
  370.     char *widgRec;        /* Bar element record */
  371.     int offset;            /* unused */
  372. {
  373.     Bar *barPtr = (Bar *)widgRec;
  374.     register int i;
  375.     int numBitmaps;
  376.     Pixmap *bitmapArr, bitmap;
  377.     char **bitmapNames;
  378.  
  379.     bitmapNames = NULL;
  380.     if (Tcl_SplitList(interp, value, &numBitmaps, &bitmapNames) != TCL_OK) {
  381.     return TCL_ERROR;
  382.     }
  383.     bitmapArr = (Pixmap *) calloc(sizeof(Pixmap), numBitmaps + 1);
  384.     if (bitmapArr == NULL) {
  385.     goto error;
  386.     }
  387.     for (i = 0; i < numBitmaps; i++) {
  388.     if (*bitmapNames[i] == '\0') {
  389.         bitmap = None;
  390.     } else {
  391.         bitmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(bitmapNames[i]));
  392.         if (bitmap == None) {
  393.         goto error;
  394.         }
  395.     }
  396.     bitmapArr[i] = bitmap;
  397.     }
  398.     free((char *)bitmapNames);
  399.     if (barPtr->bitmapArr != NULL) {
  400.     for (i = 0; i < barPtr->numBitmaps; i++) {
  401.         bitmap = barPtr->bitmapArr[i];
  402.         if (bitmap != None) {
  403.         Tk_FreeBitmap(Tk_Display(tkwin), bitmap);
  404.         }
  405.     }
  406.     free((char *)barPtr->bitmapArr);
  407.     }
  408.     barPtr->bitmapArr = bitmapArr;
  409.     if (numBitmaps == 0) {
  410.     numBitmaps = 1;
  411.     }
  412.     barPtr->numBitmaps = numBitmaps;
  413.     return TCL_OK;
  414.  
  415.   error:
  416.     if (bitmapArr != NULL) {
  417.     for (i = 0; i < numBitmaps; i++) {
  418.         if (bitmapArr[i] != None) {
  419.         Tk_FreeBitmap(Tk_Display(tkwin), bitmapArr[i]);
  420.         }
  421.     }
  422.     free((char *)bitmapArr);
  423.     }
  424.     if (bitmapNames != NULL) {
  425.     free((char *)bitmapNames);
  426.     }
  427.     return TCL_ERROR;
  428. }
  429.  
  430. /*
  431.  *----------------------------------------------------------------------
  432.  *
  433.  * PrintBitmapList --
  434.  *
  435.  *    Convert the array of bitmap pointers into a list of bitmap names.
  436.  *
  437.  * Results:
  438.  *    The string representing the list of bitmap names is returned.
  439.  *
  440.  *----------------------------------------------------------------------
  441.  */
  442. /*ARGSUSED*/
  443. static char *
  444. PrintBitmapList(clientData, tkwin, widgRec, offset, freeProcPtr)
  445.     ClientData clientData;    /* Type of axis vector to print */
  446.     Tk_Window tkwin;        /* not used */
  447.     char *widgRec;        /* Bar element record */
  448.     int offset;            /* not used */
  449.     Tcl_FreeProc **freeProcPtr;    /* Memory deallocation scheme to use */
  450. {
  451.     Bar *barPtr = (Bar *)(widgRec);
  452.     Tcl_DString buffer;
  453.     char *result;
  454.     register int i;
  455.     register char *name;
  456.  
  457.     Tcl_DStringInit(&buffer);
  458.     for (i = 0; i < barPtr->numBitmaps; i++) {
  459.     name = "";
  460.     if (barPtr->bitmapArr[i] != None) {
  461.         name = Tk_NameOfBitmap(Tk_Display(tkwin), barPtr->bitmapArr[i]);
  462.     }
  463.     Tcl_DStringAppendElement(&buffer, name);
  464.     }
  465.     result = Tcl_DStringValue(&buffer);
  466.     result = strdup(result);
  467.     *freeProcPtr = (Tcl_FreeProc *)free;
  468.     Tcl_DStringFree(&buffer);
  469.     return (result);
  470. }
  471.  
  472. /*
  473.  *----------------------------------------------------------------------
  474.  *
  475.  * ConfigureBar --
  476.  *
  477.  *    Sets up the appropriate configuration parameters in the GC.
  478.  *      It is assumed the parameters have been previously set by
  479.  *    a call to Tk_ConfigureWidget.
  480.  *
  481.  * Results:
  482.  *    The return value is a standard Tcl result.  If TCL_ERROR is
  483.  *    returned, then interp->result contains an error message.
  484.  *
  485.  * Side effects:
  486.  *    Configuration information such as bar foreground/background
  487.  *    color and stipple etc. get set in a new GC.
  488.  *
  489.  *----------------------------------------------------------------------
  490.  */
  491. /*ARGSUSED*/
  492. static int
  493. ConfigureBar(graphPtr, elemPtr)
  494.     Graph *graphPtr;
  495.     register Element *elemPtr;
  496. {
  497.     XGCValues gcValues;
  498.     unsigned long gcMask;
  499.     Bar *barPtr = (Bar *)elemPtr;
  500.     register int i;
  501.     GC *newArr, newGC;
  502.     XColor *colorPtr;
  503.     Pixmap stipple;
  504.     int numSegments;
  505.  
  506.     barPtr->symbol = SQUARE_SYMBOL;    /* Use square symbol in legend */
  507.  
  508.     gcValues.foreground = barPtr->activeFg->pixel;
  509.     gcValues.background = (Tk_3DBorderColor(barPtr->activeBorder))->pixel;
  510.     gcMask = GCForeground | GCBackground;
  511.     stipple = barPtr->bitmapArr[0];    /* Always will have at least one entry */
  512.     if (stipple != None) {
  513.     gcValues.stipple = stipple;
  514.     gcValues.fill_style = FillOpaqueStippled;
  515.     gcMask |= (GCStipple | GCFillStyle);
  516.     }
  517.     newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
  518.     if (barPtr->activeGC != NULL) {
  519.     Tk_FreeGC(graphPtr->display, barPtr->activeGC);
  520.     }
  521.     barPtr->activeGC = newGC;
  522.  
  523.     gcValues.background = (Tk_3DBorderColor(barPtr->border))->pixel;
  524.     numSegments = barPtr->y.length;
  525.     newArr = (GC *)malloc(sizeof(GC) * (numSegments + 1));
  526.     for (i = 0; i < numSegments; i++) {
  527.     colorPtr = barPtr->colorArr[i % barPtr->numColors];
  528.     gcValues.foreground = colorPtr->pixel;
  529.     stipple = barPtr->bitmapArr[i % barPtr->numBitmaps];
  530.     if (stipple != None) {
  531.         gcValues.stipple = stipple;
  532.         gcValues.fill_style = FillOpaqueStippled;
  533.         gcMask |= (GCStipple | GCFillStyle);
  534.     } else {
  535.         gcMask &= ~(GCStipple | GCFillStyle);
  536.     }
  537.     newArr[i] = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
  538.     }
  539.     newArr[i] = NULL;
  540.     if (barPtr->gcArr != NULL) {
  541.     register GC *gcPtr;
  542.  
  543.     for (gcPtr = barPtr->gcArr; *gcPtr != NULL; gcPtr++) {
  544.         Tk_FreeGC(graphPtr->display, *gcPtr);
  545.     }
  546.     free((char *)barPtr->gcArr);
  547.     }
  548.     barPtr->gcArr = newArr;
  549.     return TCL_OK;
  550. }
  551.  
  552. /*
  553.  *----------------------------------------------------------------------
  554.  *
  555.  * ComputeBarLimits --
  556.  *
  557.  *    Returns the limits of the bar data
  558.  *
  559.  * Results:
  560.  *    None.
  561.  *
  562.  *----------------------------------------------------------------------
  563.  */
  564. /*ARGSUSED*/
  565. static int
  566. ComputeBarLimits(graphPtr, elemPtr, axisPtr, minPtr, maxPtr)
  567.     Graph *graphPtr;
  568.     Element *elemPtr;
  569.     GraphAxis *axisPtr;        /* Axis information */
  570.     double *minPtr, *maxPtr;
  571. {
  572.     Bar *barPtr = (Bar *)elemPtr;
  573.     Vector *vecPtr;
  574.  
  575.     *minPtr = Blt_posInfinity, *maxPtr = Blt_negInfinity;
  576.     if ((barPtr->x.length < 1) || (barPtr->y.length < 1)) {
  577.     return 0;
  578.     }
  579.     if (!(elemPtr->axisFlags & AXIS_MASK(axisPtr))) {
  580.     return 0;
  581.     }
  582.     if (X_AXIS(axisPtr)) {
  583.     vecPtr = &(barPtr->x);
  584.     *minPtr = (axisPtr->logScale) ? vecPtr->logMin : vecPtr->min;
  585.     *minPtr -= 0.5;
  586.     *maxPtr = vecPtr->max + 0.5;
  587.     } else {
  588.     vecPtr = &(barPtr->y);
  589.     *maxPtr = vecPtr->max;
  590.     *minPtr = (axisPtr->logScale) ? vecPtr->logMin : vecPtr->min;
  591.  
  592.     /* Stacked vector may either change the max or min */
  593.     if (barPtr->stacked) {
  594.         register int i;
  595.         double sum = 0.0;
  596.  
  597.         for (i = 0; i < vecPtr->length; i++) {
  598.         sum += vecPtr->data[i];
  599.         }
  600.         if (sum > *maxPtr) {
  601.         *maxPtr = sum;
  602.         } else if (sum < *minPtr) {
  603.         *minPtr = sum;
  604.         }
  605.     }
  606.     }
  607.     return (vecPtr->length);
  608. }
  609.  
  610. /*
  611.  *----------------------------------------------------------------------
  612.  *
  613.  * ClosestBar --
  614.  *
  615.  *    Find the bar segment closest to the window coordinates    point
  616.  *    specified.
  617.  *
  618.  * Results:
  619.  *    Returns 1 if the point is width any bar segment, otherwise 0.
  620.  *    Does not currently use graphPtr->halo.
  621.  *
  622.  *----------------------------------------------------------------------
  623.  */
  624. /*ARGSUSED*/
  625. static int
  626. ClosestBar(graphPtr, elemPtr, winX, winY, closePtr)
  627.     Graph *graphPtr;        /* Graph widget record */
  628.     Element *elemPtr;        /* Bar element */
  629.     int winX, winY;        /* Window coordinates of point on screen */
  630.     ClosestPoint *closePtr;    /* Index of closest point in element */
  631. {
  632.     Bar *barPtr = (Bar *)elemPtr;
  633.     register int i, n;
  634.     double sum;
  635.     int delta[3];
  636.     int barDist, maxDist;
  637.     register XRectangle *rectPtr;
  638.  
  639.     if (barPtr->numSegments == 0) {
  640.     return 0;
  641.     }
  642.     sum = 0.0;
  643.     barDist = (graphPtr->halo + 1);
  644.     for (i = 0; i < barPtr->numSegments; i++) {
  645.     rectPtr = &(barPtr->segments[i]);
  646.     if (barPtr->stacked) {
  647.         sum += barPtr->y.data[i];
  648.     }
  649.     maxDist = (rectPtr->x - winX);
  650.     delta[0] = (winX - (rectPtr->x + rectPtr->width));
  651.     delta[1] = (rectPtr->y - winY);
  652.     delta[2] = (winY - (rectPtr->y + rectPtr->height));
  653.     for (n = 0; n < 3; n++) {
  654.         if (delta[n] > maxDist) {
  655.         maxDist = delta[n];
  656.         }
  657.     }
  658.     /* If it's in the bounding box, then this is the segment */
  659.     if (maxDist <= 0) {
  660.         closePtr->elemPtr = elemPtr;
  661.         closePtr->index = i;
  662.         closePtr->x = barPtr->x.data[0];
  663.         closePtr->y = (barPtr->stacked) ? sum : barPtr->y.data[i];
  664.         closePtr->dist = 0.0;
  665.         return 1;
  666.     }
  667.     /*
  668.      * If it's in the extended bounding box, save the distance and
  669.      * the index of the segement closest to the edge
  670.      */
  671.     if (maxDist < barDist) {
  672.         barDist = maxDist;
  673.         closePtr->index = i;
  674.         closePtr->y = (barPtr->stacked) ? sum : barPtr->y.data[i];
  675.     }
  676.     }
  677.     if (barDist <= graphPtr->halo) {
  678.     closePtr->elemPtr = elemPtr;
  679.     closePtr->x = barPtr->x.data[0];
  680.     closePtr->dist = barDist;
  681.     return 1;
  682.     }
  683.     return 0;
  684. }
  685.  
  686. /*
  687.  *----------------------------------------------------------------------
  688.  *
  689.  * LayoutBar --
  690.  *
  691.  *    Calculates the actual window coordinates of the bar element.
  692.  *    The window coordinates are saved in the bar element structure.
  693.  *
  694.  * Results:
  695.  *    None.
  696.  *
  697.  * Notes:
  698.  *    A bar can have multiple y values.  In this case, the bar can be
  699.  *     represented as either a set of contiguous bars (no spacing) or a
  700.  *      single multi-segmented (stacked) bar.
  701.  *
  702.  *    The X axis layout for a barchart may be presented in one of two ways.
  703.  *    If x values are used, the bars are placed at those coordinates.
  704.  *    Otherwise, the range will represent the number of values.
  705.  *
  706.  *----------------------------------------------------------------------
  707.  */
  708. static void
  709. LayoutBar(graphPtr, elemPtr)
  710.     Graph *graphPtr;
  711.     Element *elemPtr;
  712. {
  713.     Bar *barPtr = (Bar *)elemPtr;
  714.     double sum;            /* Sum of bar y values */
  715.     double avgSize;
  716.     int curX, curY;        /* Current and last Y positions */
  717.     int lastY, delta;        /* Last y-coordinate used */
  718.     XRectangle *segArr;
  719.     int avgWidth;        /* Width of each bar in set */
  720.     GraphAxis *X, *Y;
  721.     int x, y, width, height;
  722.     register int i;
  723.     int numSegments;
  724.  
  725.     if ((barPtr->x.length < 1) || (barPtr->y.length < 1)) {
  726.     return;            /* No bars */
  727.     }
  728.     /* Determine which axes the bar element is mapped to */
  729.     X = (barPtr->axisFlags & X1_AXIS_MASK)
  730.     ? graphPtr->axisArr[X1_AXIS] : graphPtr->axisArr[X2_AXIS];
  731.     Y = (barPtr->axisFlags & Y1_AXIS_MASK)
  732.     ? graphPtr->axisArr[Y1_AXIS] : graphPtr->axisArr[Y2_AXIS];
  733.  
  734.     segArr = barPtr->segArr;
  735.     numSegments = barPtr->y.length;
  736.     if (numSegments > DEF_SEG_SIZE) {
  737.     segArr = (XRectangle *)malloc(barPtr->y.length * sizeof(XRectangle));
  738.     if (segArr == NULL) {
  739.         return;
  740.     }
  741.     }
  742.     curY = lastY = Blt_Transform(Y, 0.0);    /* Baseline of bars */
  743.  
  744.     /* Watch out for limiting of values */
  745.     avgWidth = Blt_TransformDist(X, graphPtr->barWidth);
  746.     if (avgWidth < 1) {
  747.     avgWidth = 1;
  748.     }
  749.     /* Use only the first data value in the X array for positioning */
  750.     curX = Blt_Transform(X, barPtr->x.data[0]) - avgWidth / 2;
  751.     sum = 0.0;
  752.     if (!barPtr->stacked) {
  753.     avgWidth /= barPtr->y.length;
  754.     }
  755.     width = avgWidth - (barPtr->padX * 2);
  756.     for (i = 0; i < barPtr->y.length; i++) {
  757.     x = curX;
  758.     if (barPtr->stacked) {
  759.         /* Next point is the current sum the y values */
  760.         sum += barPtr->y.data[i];
  761.         lastY = curY;
  762.         curY = Blt_Transform(Y, sum);
  763.     } else {
  764.         curY = Blt_Transform(Y, barPtr->y.data[i]);
  765.         curX += avgWidth;    /* Adjust x-coordinate by next bar width */
  766.     }
  767.     if (barPtr->y.max < 0.0) {
  768.         y = lastY;        /* Origin is last y-coordinate */
  769.         delta = curY - lastY;
  770.     } else {
  771.         y = curY;        /* Origin is current y-coordinate */
  772.         delta = lastY - curY;
  773.     }
  774.     height = BLT_ABS(delta) + 1;
  775.     if (graphPtr->inverted) {
  776.         segArr[i].y = x;
  777.         segArr[i].x = y - height;
  778.         segArr[i].width = height;
  779.         segArr[i].height = width;
  780.     } else {
  781.         segArr[i].x = x;
  782.         segArr[i].y = y;
  783.         segArr[i].width = width;
  784.         segArr[i].height = height;
  785.     }
  786.     }
  787.     avgSize = graphPtr->avgSymSize * barPtr->symbolScale;
  788.     barPtr->symbolSize = BLT_RND(avgSize);
  789.     if (barPtr->segments != barPtr->segArr) {
  790.     free((char *)barPtr->segments);
  791.     }
  792.     barPtr->numSegments = numSegments;
  793.     barPtr->segments = segArr;
  794. }
  795.  
  796. /*
  797.  * -----------------------------------------------------------------
  798.  *
  799.  * DrawSymbols --
  800.  *
  801.  *     Draw a symbol centered at the given x,y window coordinate
  802.  *    based upon the element symbol type and size.
  803.  *
  804.  * Results:
  805.  *    None.
  806.  *
  807.  * Problems:
  808.  *    Most notable is the round-off errors generated when
  809.  *    calculating the centered position of the symbol.
  810.  * -----------------------------------------------------------------
  811.  */
  812. /*ARGSUSED*/
  813. static void
  814. DrawSymbols(graphPtr, elemPtr, size, pointArr, numPoints, active)
  815.     Graph *graphPtr;
  816.     Element *elemPtr;
  817.     int size;
  818.     XPoint *pointArr;
  819.     int numPoints;
  820.     int active;            /* unused */
  821. {
  822.     Bar *barPtr = (Bar *)elemPtr;
  823.     register int i;
  824.     int x, y, radius;
  825.  
  826.     radius = (size / 2);
  827.     size--;
  828.     for (i = 0; i < numPoints; i++) {
  829.     x = pointArr[i].x - radius, y = pointArr[i].y - radius;
  830.     XFillRectangle(graphPtr->display, graphPtr->canvas, barPtr->gcArr[0],
  831.         x, y, size, size);
  832.     }
  833. }
  834.  
  835. /*
  836.  *----------------------------------------------------------------------
  837.  *
  838.  * DisplayBar --
  839.  *
  840.  *    Draws the rectangle representing the bar element.
  841.  *    If the relief option is set to "raised" or "sunken" and the
  842.  *    bar borderwidth is set (borderwidth > 0), a 3D border is
  843.  *    drawn around the bar.
  844.  *
  845.  * Results:
  846.  *    None.
  847.  *
  848.  * Side effects:
  849.  *    X drawing commands are output.
  850.  *
  851.  *----------------------------------------------------------------------
  852.  */
  853. static void
  854. DisplayBar(graphPtr, elemPtr, active)
  855.     Graph *graphPtr;
  856.     Element *elemPtr;
  857.     int active;
  858. {
  859.     Bar *barPtr = (Bar *)elemPtr;
  860.     register int i;
  861.     Tk_3DBorder border;
  862.     GC gc;
  863.     unsigned int numRects;
  864.     unsigned int index, maxIndex;
  865.     int useIndex;
  866.  
  867.     if (active) {
  868.     gc = barPtr->activeGC;
  869.     border = barPtr->activeBorder;
  870.     } else {
  871.     border = barPtr->border;
  872.     }
  873.  
  874.     numRects = barPtr->numSegments;
  875.     useIndex = ((active) && (barPtr->numActivePoints > 0));
  876.     if (useIndex) {
  877.     maxIndex = numRects - 1;
  878.     numRects = barPtr->numActivePoints;
  879.     }
  880.     for (i = 0; i < numRects; i++) {
  881.     index = i;
  882.     if (useIndex) {
  883.         index = barPtr->activeArr[i];
  884.         if (index > maxIndex) {
  885.         continue;
  886.         }
  887.     }
  888.     if (!active) {
  889.         gc = barPtr->gcArr[index];
  890.     }
  891.     XFillRectangle(graphPtr->display, graphPtr->canvas, gc,
  892.         barPtr->segments[index].x, barPtr->segments[index].y,
  893.         barPtr->segments[index].width, barPtr->segments[index].height);
  894.     if ((barPtr->borderWidth > 0) && (barPtr->relief != TK_RELIEF_FLAT)) {
  895.         Tk_Draw3DRectangle(graphPtr->tkwin, graphPtr->canvas,
  896.         border, barPtr->segments[index].x, barPtr->segments[index].y,
  897.         barPtr->segments[index].width, barPtr->segments[index].height,
  898.         barPtr->borderWidth, barPtr->relief);
  899.     }
  900.     }
  901. }
  902.  
  903. /*
  904.  * -----------------------------------------------------------------
  905.  *
  906.  * PrintSymbols --
  907.  *
  908.  *     Draw a symbol centered at the given x,y window coordinate
  909.  *    based upon the element symbol type and size.
  910.  *
  911.  * Results:
  912.  *    None.
  913.  *
  914.  * Problems:
  915.  *    Most notable is the round-off errors generated when
  916.  *    calculating the centered position of the symbol.
  917.  * -----------------------------------------------------------------
  918.  */
  919. /*ARGSUSED*/
  920. static void
  921. PrintSymbols(graphPtr, elemPtr, size, pointArr, numPoints, active)
  922.     Graph *graphPtr;
  923.     Element *elemPtr;
  924.     int size;
  925.     XPoint *pointArr;
  926.     int numPoints;
  927.     int active;
  928. {
  929.     Bar *barPtr = (Bar *)elemPtr;
  930.     register int i;
  931.     XColor *normalFg;
  932.     Pixmap stipple;
  933.  
  934.     stipple = barPtr->bitmapArr[0];
  935.     if (stipple != None) {
  936.     int width, height;
  937.  
  938.     Blt_BackgroundToPostScript(graphPtr, Tk_3DBorderColor(barPtr->border));
  939.     Tcl_AppendResult(graphPtr->interp, "/StippleProc {\ngsave\n",
  940.         (char *)NULL);
  941.     Tk_SizeOfBitmap(graphPtr->display, stipple, &width, &height);
  942.     Blt_StippleToPostScript(graphPtr, stipple, width, height, 1);
  943.     Tcl_AppendResult(graphPtr->interp, "} def\n", (char *)NULL);
  944.     }
  945.     for (i = 0; i < numPoints; i++) {
  946.     normalFg = barPtr->colorArr[(i % barPtr->numColors)];
  947.     if (stipple == None) {
  948.         Blt_ForegroundToPostScript(graphPtr, normalFg);
  949.     }
  950.     sprintf(graphPtr->scratchPtr, "%d %d %d Sq\n", pointArr[i].x,
  951.         pointArr[i].y, size);
  952.     Tcl_AppendResult(graphPtr->interp, graphPtr->scratchPtr, (char *)NULL);
  953.     if (stipple != None) {
  954.         Tcl_AppendResult(graphPtr->interp, "gsave\n", (char *)NULL);
  955.         Blt_ForegroundToPostScript(graphPtr, normalFg);
  956.         Tcl_AppendResult(graphPtr->interp, "/StippleProc cvx exec\n",
  957.         "grestore\n", (char *)NULL);
  958.     }
  959.     }
  960. }
  961.  
  962. /*
  963.  *----------------------------------------------------------------------
  964.  *
  965.  * PrintBar --
  966.  *
  967.  *    Similar to the DrawBar procedure, prints PostScript related
  968.  *    commands to form rectangle representing the bar element.
  969.  *
  970.  * Results:
  971.  *    None.
  972.  *
  973.  * Side effects:
  974.  *    PostScript pen width, dashes, and color settings are changed.
  975.  *
  976.  *----------------------------------------------------------------------
  977.  */
  978. /*ARGSUSED*/
  979. static void
  980. PrintBar(graphPtr, elemPtr, active)
  981.     Graph *graphPtr;
  982.     Element *elemPtr;
  983.     int active;            /* Unused */
  984. {
  985.     Bar *barPtr = (Bar *)elemPtr;
  986.     register int i;
  987.     XColor *normalFg;
  988.     register Pixmap stipple;
  989.  
  990.     for (i = 0; i < barPtr->numSegments; i++) {
  991.     normalFg = barPtr->colorArr[(i % barPtr->numColors)];
  992.     stipple = barPtr->bitmapArr[(i % barPtr->numBitmaps)];
  993.     if (stipple != None) {
  994.         int width, height;
  995.  
  996.         Blt_BackgroundToPostScript(graphPtr,
  997.         Tk_3DBorderColor(barPtr->border));
  998.         Blt_RectangleToPostScript(graphPtr, barPtr->segments[i].x,
  999.         barPtr->segments[i].y, barPtr->segments[i].width,
  1000.         barPtr->segments[i].height);
  1001.         Tk_SizeOfBitmap(graphPtr->display, stipple, &width, &height);
  1002.         Blt_ForegroundToPostScript(graphPtr, normalFg);
  1003.         Blt_StippleToPostScript(graphPtr, stipple, width, height, True);
  1004.     } else {
  1005.         Blt_ForegroundToPostScript(graphPtr, normalFg);
  1006.         Blt_RectangleToPostScript(graphPtr, barPtr->segments[i].x,
  1007.         barPtr->segments[i].y, barPtr->segments[i].width,
  1008.         barPtr->segments[i].height);
  1009.     }
  1010.     if ((barPtr->borderWidth > 0) &&
  1011.         (barPtr->relief != TK_RELIEF_FLAT)) {
  1012.         Blt_Print3DRectangle(graphPtr, barPtr->border,
  1013.         barPtr->segments[i].x, barPtr->segments[i].y,
  1014.         (unsigned int)barPtr->segments[i].width,
  1015.         barPtr->segments[i].height, barPtr->borderWidth,
  1016.         barPtr->relief);
  1017.     }
  1018.     }
  1019. }
  1020.  
  1021. /*
  1022.  *----------------------------------------------------------------------
  1023.  *
  1024.  * DestroyBar --
  1025.  *
  1026.  *    Release memory and resources allocated for the bar element.
  1027.  *
  1028.  * Results:
  1029.  *    None.
  1030.  *
  1031.  * Side effects:
  1032.  *    Everything associated with the bar element is freed up.
  1033.  *
  1034.  *----------------------------------------------------------------------
  1035.  */
  1036. static void
  1037. DestroyBar(graphPtr, elemPtr)
  1038.     Graph *graphPtr;
  1039.     Element *elemPtr;
  1040. {
  1041.     Bar *barPtr = (Bar *)elemPtr;
  1042.  
  1043.     Tk_FreeOptions(barPtr->configSpecs, (char *)barPtr, graphPtr->display, 0);
  1044.  
  1045.     if (barPtr->gcArr != NULL) {
  1046.     register GC *gcPtr;
  1047.  
  1048.     for (gcPtr = barPtr->gcArr; *gcPtr != NULL; gcPtr++) {
  1049.         Tk_FreeGC(graphPtr->display, *gcPtr);
  1050.     }
  1051.     free((char *)barPtr->gcArr);
  1052.     }
  1053.     if (barPtr->activeGC != NULL) {
  1054.     Tk_FreeGC(graphPtr->display, barPtr->activeGC);
  1055.     }
  1056.     if (barPtr->colorArr != NULL) {
  1057.     register XColor **colorPtrPtr;
  1058.  
  1059.     for (colorPtrPtr = barPtr->colorArr; *colorPtrPtr != NULL;
  1060.         colorPtrPtr++) {
  1061.         Tk_FreeColor(*colorPtrPtr);
  1062.     }
  1063.     free((char *)barPtr->colorArr);
  1064.     }
  1065.     if (barPtr->bitmapArr != NULL) {
  1066.     register int i;
  1067.  
  1068.     for (i = 0; i < barPtr->numBitmaps; i++) {
  1069.         if (barPtr->bitmapArr[i] != None) {
  1070.         Tk_FreeBitmap(graphPtr->display, barPtr->bitmapArr[i]);
  1071.         }
  1072.     }
  1073.     free((char *)barPtr->bitmapArr);
  1074.     }
  1075.     if (barPtr->segments != barPtr->segArr) {
  1076.     free((char *)barPtr->segments);
  1077.     }
  1078.     if (barPtr->x.data != NULL) {
  1079.     free((char *)barPtr->x.data);
  1080.     }
  1081.     if (barPtr->y.data != NULL) {
  1082.     free((char *)barPtr->y.data);
  1083.     }
  1084.     if (barPtr->activeArr != barPtr->staticArr) {
  1085.     free((char *)barPtr->activeArr);
  1086.     }
  1087.     free((char *)barPtr);
  1088. }
  1089.  
  1090. /*
  1091.  *----------------------------------------------------------------------
  1092.  *
  1093.  * CreateBar --
  1094.  *
  1095.  *    Allocate memory and initialize methods for the new bar element.
  1096.  *
  1097.  * Results:
  1098.  *    The pointer to the newly allocated element structure is returned.
  1099.  *
  1100.  * Side effects:
  1101.  *    Memory is allocated for the bar element structure.
  1102.  *
  1103.  *----------------------------------------------------------------------
  1104.  */
  1105. Element *
  1106. Blt_BarElement()
  1107. {
  1108.     register Bar *barPtr;
  1109.  
  1110.     barPtr = (Bar *)calloc(1, sizeof(Bar));
  1111.     if (barPtr == NULL) {
  1112.     return NULL;
  1113.     }
  1114.     barPtr->configSpecs = configSpecs;
  1115.     barPtr->configProc = ConfigureBar;
  1116.     barPtr->destroyProc = DestroyBar;
  1117.     barPtr->displayProc = DisplayBar;
  1118.     barPtr->limitsProc = ComputeBarLimits;
  1119.     barPtr->closestProc = ClosestBar;
  1120.     barPtr->layoutProc = LayoutBar;
  1121.     barPtr->printProc = PrintBar;
  1122.     barPtr->drawSymbolsProc = DrawSymbols;
  1123.     barPtr->printSymbolsProc = PrintSymbols;
  1124.  
  1125.     barPtr->type = BAR_ELEM_TYPE;
  1126.     barPtr->relief = TK_RELIEF_RAISED;
  1127.     barPtr->symbolScale = 1.0;
  1128.     barPtr->borderWidth = 2;
  1129.     barPtr->stacked = 0;
  1130.     barPtr->numBitmaps = barPtr->numSegments = barPtr->numColors = 0;
  1131.     barPtr->segments = barPtr->segArr;
  1132.     return ((Element *)barPtr);
  1133. }
  1134.